package com.mytijian.task.config;

import com.mytijian.task.lifecycle.ApplicationLifycycleContainer;
import com.mytijian.task.repository.RuningTaskRepository;
import com.mytijian.task.repository.database.repository.MysqlTaskRepository;
import com.mytijian.task.repository.redis.RedisConfig;
import com.mytijian.task.repository.redis.RuningTaskRedisRepository;
import com.mytijian.task.task.TaskIdentifyOperateServiceImpl;
import com.mytijian.task.task.handout.DefaultHandoutController;
import com.mytijian.task.task.handout.HandoutController;
import com.mytijian.task.task.listener.FailoverLogStoreListener;
import com.mytijian.task.task.listener.FailoverTaskIndentifyListener;
import com.mytijian.task.zookeeper.LeaderService;
import com.mytijian.task.zookeeper.NodeService;
import com.mytijian.task.zookeeper.ZookeeperConfig;
import com.mytijian.task.zookeeper.ZookeeperRegistryCenter;
import com.mytijian.task.zookeeper.listener.manager.LeaderListenerManager;
import com.mytijian.task.zookeeper.listener.manager.NodeListenerManager;
import com.mytijian.task.lifecycle.ApplicationLifycycle;
import com.mytijian.task.repository.TaskRepository;
import com.mytijian.task.task.AbstractTaskProcess;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PreDestroy;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Configuration
public class TaskConfig implements InitializingBean{
    @Autowired
    private ServerProperties serverProperties;
    @Autowired
    private List<ApplicationLifycycle> applicationLifycycles;
    @Bean
    public TaskRepository mysqlTaskRepository() {
        return new MysqlTaskRepository();
    }
    @Bean
    public ZookeeperRegistryCenter zookeeperRegistryCenter() {
        ZookeeperConfig zookeeperConfig = new ZookeeperConfig();
        zookeeperConfig.setConnectionString("192.168.5.4:2181");
        zookeeperConfig.setNameSpace("mtjk-task");
        ZookeeperRegistryCenter zookeeperRegistryCenter = new ZookeeperRegistryCenter(zookeeperConfig);
        zookeeperRegistryCenter.init();
        return zookeeperRegistryCenter;
    }
    @Bean
    public LeaderService leaderService(ZookeeperRegistryCenter zookeeperRegistryCenter, ServerProperties properties) {
        LeaderService leaderService = new LeaderService(zookeeperRegistryCenter, properties.getPort());
        leaderService.executeInLeader();
        return leaderService;
    }
    @Bean
    public NodeService nodeService(ZookeeperRegistryCenter zookeeperRegistryCenter, ServerProperties properties) {
        NodeService nodeService = new NodeService(zookeeperRegistryCenter, properties.getPort());
        nodeService.init();
        return nodeService;
    }
    @Bean
    public NodeListenerManager nodeListenerManager(ZookeeperRegistryCenter zookeeperRegistryCenter,
                                                   LeaderService leaderService,
                                                   RuningTaskRepository runingTaskRepository,
                                                   TaskRepository taskRepository) {
        HandoutController handoutController = new DefaultHandoutController(zookeeperRegistryCenter, leaderService, runingTaskRepository, taskRepository);
        NodeListenerManager nodeListenerManager = new NodeListenerManager(zookeeperRegistryCenter, leaderService, handoutController,serverProperties.getServlet().getContextPath());
        nodeListenerManager.start();
        return nodeListenerManager;
    }
    @Bean
    public LeaderListenerManager leaderListenerManager(ZookeeperRegistryCenter zookeeperRegistryCenter, LeaderService leaderService) {
        LeaderListenerManager leaderListenerManager = new LeaderListenerManager(zookeeperRegistryCenter, leaderService);
        leaderListenerManager.start();
        return leaderListenerManager;
    }
    @Bean
    public TaskIdentifyOperateServiceImpl taskIdentifyOperateService(RuningTaskRedisRepository runingTaskRedisRepository,
                                                                     List<AbstractTaskProcess> abstractTaskLaunches,
                                                                     TaskRepository taskRepository) {
        TaskIdentifyOperateServiceImpl taskIdentifyOperateService = new TaskIdentifyOperateServiceImpl(taskRepository, abstractTaskLaunches ,runingTaskRedisRepository);
        runingTaskRedisRepository.addRunTaskListener(new FailoverTaskIndentifyListener(taskIdentifyOperateService));
        return taskIdentifyOperateService;
    }
    @Bean
    public RuningTaskRedisRepository runingTaskRedisRepository(LeaderService leaderService, TaskRepository taskRepository) {
        RedisConfig redisConfig = new RedisConfig();
        redisConfig.setHostName("192.168.5.4");
        redisConfig.setPassword("mytijian");
        redisConfig.setPort(6379);
        RuningTaskRedisRepository runingTaskRedisRepository = new RuningTaskRedisRepository(leaderService, taskRepository, redisConfig);
        runingTaskRedisRepository.addRunTaskListener(new FailoverLogStoreListener(taskRepository));
        return runingTaskRedisRepository;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Collection<ApplicationLifycycle> collection = applicationLifycycles.stream().sorted(Comparator.comparing(ApplicationLifycycle::initSort)).collect(Collectors.toList());
        for (ApplicationLifycycle applicationLifycycle : collection) {
            applicationLifycycle.init();
        }
    }
}
